﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Shell.PocoDot;

namespace Shell.DomainDot
{
    public class MainInjector : DomainInjector
    {
        private static Type typeSupported;
        private IDataContextFactory factory;

        static MainInjector()
        {
            typeSupported = typeof(Main<>);
        }

        public MainInjector()
        {
            this.factory = ObjectSeeker.Seeker.Seek<IDataContextFactory>();
        }

        protected override Type TargetDomainType
        {
            get { return typeSupported; }
        }

        protected override IEnumerable<PropertyInfo> GetInjectingProperties<TDomainDot>(TDomainDot dot)
        {
            if (dot.Context.Key.HasValue)
            {
                return base.GetInjectingProperties(dot);
            }
            return Enumerable.Empty<PropertyInfo>();
        }

        protected override object CreateDomainDot<TDomainDot>(TDomainDot dot, PropertyInfo domainSegment)
        {
            if (dot.Context.Key.HasValue)
            {
                var c = domainSegment.PropertyType.GetConstructors()[0];
                var respository = this.MakePocoRepository(domainSegment);
                return c.Invoke(new object[] { dot.Context.Key.Value, respository });
            }
            return null;
        }

        protected virtual IPersistent MakePocoRepository(PropertyInfo domainSegment)
        {
            var factoryType = this.factory.GetType();
            var createMethod = factoryType.GetMethod("Create");
            var pocoArgument = this.GetPocoType(domainSegment);
            if (pocoArgument == null)
            {
                //TODO                
            }

            var m = createMethod.MakeGenericMethod(pocoArgument);
            var repository = m.Invoke(factory, new object[] { });
            return repository == null ? null : repository as IPersistent;
        }

        protected virtual Type GetPocoType(PropertyInfo domainSegment)
        {
            return DomainInjectHelper.GetPocoType(domainSegment);
        }

        protected override void OnDispose(bool disposing)
        {
            if (disposing)
            {
                this.factory = null;
            }
        }
    }
}
